package SSF.OS.TCP;

import SSF.OS.*;
import SSF.Net.Util.*;
import SSF.OS.Socket.*;
/** 
 * TCP_Message represents a TCP header and data segment together with
 * the prepended IpHeader.
 */
public class TCP_Message extends TCP_Header
{
  /** segment length of this TCP message*/
  public int seglen;

  /** Convenience method to get the prepended IP header. */
  IpHeader ipHeader() {
    return ((IpHeader)previous());
  }

  /** destination IP address of this TCP message. Obsolete. */
  int DestAddr() {
    return ipHeader().DEST_IP;
  };

  /** Construct a TCP message with TCP header th, including a prepended
   *  IpHeader with given destination IP address destAddr,
   *  source IP address set to -1, and virtual segment length len bytes.
   *  Obsolete.
   */
  public TCP_Message(TCP_Header th, int destAddr, int len ){
    super(th);
    IpHeader iphdr = new IpHeader(Protocols.TCP_PRTL_NUM,-1,destAddr); 
    iphdr.carryPayload(this);
    seglen = len;
    System.err.println("Warning: TCP_Message: obsolete constructor used");
  }

  /** Construct a TCP message with TCP header th, including a prepended
   *  IpHeader with source IP address srcAddr, destination IP address
   *  destAddr, and virtual segment length len bytes.
   *  Modification here and in other SSF.OS.TCP classes by BJ Premore
   *  9/22/00.
   */
  public TCP_Message(TCP_Header th, int srcAddr, int destAddr, int len ){
    super(th);
    IpHeader iphdr = new IpHeader(Protocols.TCP_PRTL_NUM,srcAddr,destAddr);
    iphdr.carryPayload(this);
    seglen = len;
  }

  /** Copy constructor used with retransmission: copies the prepended
   *  IpHeader's fields SOURCE_IP, DEST_IP, TOS, but NOT the TTL field, which
   *  is set to the default value.
   *  Fragile: should not be used except by SSF.OS.TCP.
   *  Modification by ato 9/24/00.
   */
  public TCP_Message(TCP_Message msg) throws ProtocolException{
    super((TCP_Header)msg);
    seglen = msg.seglen;

    IpHeader iphdr = new IpHeader(Protocols.TCP_PRTL_NUM,
                                  msg.ipHeader().SOURCE_IP,
                                  msg.ipHeader().DEST_IP);
    // copy other fields in the IP header
    iphdr.TOS = msg.ipHeader().TOS;

    iphdr.carryPayload(this);
    ProtocolMessage pMsg = msg.payload();
    if(pMsg == null)return;
    if(pMsg instanceof dataMessage){
      carryPayload(new dataMessage((dataMessage)pMsg));
    }else {
      throw new ProtocolException("TCP: unknown payload type!");
    }
  }
  /* Prints out the content of the TCP message. */
  public void printMsg(){
    System.out.println("{s=" + IP_s.IPtoString(ipHeader().SOURCE_IP)
                       + ": d= " + IP_s.IPtoString(ipHeader().DEST_IP)
                       + " [sPort: "+ SOURCE_port + " dPort: " 
                       + DEST_port + " SEQno: " + SEQno + " ACKno: " 
                       + ACKno + " flags: " + flags + " size: " 
                       + seglen + " advWnd: " + AdvertisedWnd + "]}" );
  }

  /** Returns the sequence number of the last byte in this segment. */
  public long getLastSEQ(){
    return SEQno + seglen - 1;
  }

  /**
   * Returns the total number of bytes contained in this TCP packet
   * (header + data).
   */
  public int bytecount(){
    int bc = super.bytecount()+seglen;
    return bc; 
  }
}
